type QueryParams = Record<string, any>

interface RouterOptions {
  success?: () => void
  fail?: (err: any) => void
  complete?: () => void
  refreshPrev?: boolean // 是否刷新上一个页面
}

/**
 * 路由跳转策略接口
 */
interface RouterStrategy {
  navigate(url: string, query: QueryParams, options: RouterOptions): void
}

/**
 * 普通页面跳转策略
 */
class NavigateToStrategy implements RouterStrategy {
  navigate(url: string, query: QueryParams, options: RouterOptions) {
    uni.navigateTo({
      url: this.formatUrl(url, query),
      ...options,
    })
  }

  private formatUrl(url: string, query: QueryParams): string {
    const queryStr = Object.keys(query)
      .map((key) => `${encodeURIComponent(key)}=${encodeURIComponent(query[key])}`)
      .join('&')
    return queryStr ? `${url}?${queryStr}` : url
  }
}

/**
 * 页面重定向策略
 */
class RedirectToStrategy implements RouterStrategy {
  navigate(url: string, query: QueryParams, options: RouterOptions) {
    uni.redirectTo({
      url: this.formatUrl(url, query),
      ...options,
    })
  }

  private formatUrl(url: string, query: QueryParams): string {
    const queryStr = Object.keys(query)
      .map((key) => `${encodeURIComponent(key)}=${encodeURIComponent(query[key])}`)
      .join('&')
    return queryStr ? `${url}?${queryStr}` : url
  }
}

/**
 * TabBar 页面跳转策略
 */
class SwitchTabStrategy implements RouterStrategy {
  navigate(url: string, _query: QueryParams, options: RouterOptions) {
    uni.switchTab({
      url,
      ...options,
    })
  }
}

/**
 * 路由管理类，使用策略模式 + 通用方法
 */
class Router {
  private tabBarPages: string[] = ['/pages/home/index', '/pages/tab1/index', '/pages/tab2/index']

  private strategy: RouterStrategy | null = null

  /**
   * 通用页面跳转
   * 根据页面类型（TabBar 或普通页面）决定使用 switchTab 或 navigateTo/redirectTo
   * @param method 跳转方式 ('navigateTo' | 'redirectTo')
   * @param route 路由地址，可以是字符串或对象
   * @param query query 参数
   * @param options 跳转选项
   */
  private navigate(
    method: 'navigateTo' | 'redirectTo',
    route: string | { url: string; query?: QueryParams },
    query: QueryParams = {},
    options: RouterOptions = {},
  ) {
    this.setStrategy(method, route)
    this.strategy?.navigate(this.resolveUrl(route), query, {
      ...options,
      complete: () => {
        if (options.refreshPrev) {
          this.refreshPrevPage()
        }
        options.complete?.()
      },
    })
  }

  /**
   * push 跳转 (类似 navigateTo)
   * @param route 跳转地址，可以是字符串或对象
   * @param query query 参数
   * @param options 额外的选项，如 success 和 fail 回调，以及是否刷新上一个页面
   */
  push(
    route: string | { url: string; query?: QueryParams },
    query: QueryParams = {},
    options: RouterOptions = {},
  ) {
    this.navigate('navigateTo', route, query, options)
  }

  /**
   * redirect 跳转 (类似 redirectTo)
   * @param route 跳转地址，可以是字符串或对象
   * @param query query 参数
   * @param options 额外的选项，如 success 和 fail 回调，以及是否刷新上一个页面
   */
  redirect(
    route: string | { url: string; query?: QueryParams },
    query: QueryParams = {},
    options: RouterOptions = {},
  ) {
    this.navigate('redirectTo', route, query, options)
  }

  /**
   * back 回退
   * @param delta 回退页面层级，默认回退 1 层
   * @param options 额外的选项，如是否刷新上一个页面
   */
  back(delta: number = 1, options: RouterOptions = {}) {
    uni.navigateBack({
      delta,
      complete: () => {
        if (options.refreshPrev) {
          this.refreshPrevPage()
        }
        options.complete?.()
      },
    })
  }

  /**
   * 设置路由策略
   * @param method 跳转方式 ('navigateTo' | 'redirectTo')
   * @param route 路由地址
   */
  private setStrategy(method: 'navigateTo' | 'redirectTo', route: string | { url: string }) {
    const url = this.resolveUrl(route)
    if (this.isTabBarPage(url)) {
      this.strategy = new SwitchTabStrategy()
    } else if (method === 'navigateTo') {
      this.strategy = new NavigateToStrategy()
    } else if (method === 'redirectTo') {
      this.strategy = new RedirectToStrategy()
    }
  }

  /**
   * 刷新上一个页面
   * 调用上一个页面的 onLoad 方法
   */
  private refreshPrevPage() {
    const pages = getCurrentPages()
    if (pages.length > 1) {
      const prevPage = pages[pages.length - 2]
      if (prevPage && typeof prevPage.onLoad === 'function') {
        prevPage.onLoad()
      } else {
        console.warn('上一个页面没有 onLoad 方法')
      }
    } else {
      console.warn('没有可刷新页面')
    }
  }

  /**
   * 判断页面是否为 TabBar 页面
   * @param url 页面路径
   * @returns 是否为 TabBar 页面
   */
  private isTabBarPage(url: string): boolean {
    return this.tabBarPages.includes(url)
  }

  /**
   * 解析传入的路由，返回 url
   * @param route 字符串或对象形式的路由
   * @returns url 地址
   */
  private resolveUrl(route: string | { url: string }): string {
    if (typeof route === 'string') {
      return route
    } else if (route.url) {
      return route.url
    }
    throw new Error('无效的路由参数')
  }
}

// 导出路由实例
export default new Router()
